#ifndef DATATYPES_H_
#define DATATYPES_H_

typedef struct atomic_concept AtomicConcept;
typedef struct conjunction Conjunction;
typedef struct existential_restriction Exists;
typedef union concept_description ConceptDescription;
typedef struct concept Concept;

typedef struct atomic_role AtomicRole;
typedef struct role_composition RoleComposition;
typedef union role_description RoleDescription;
typedef struct role Role;

typedef union expression Expression;

typedef struct subclass_axiom SubClassAxiom;
typedef struct eqclass_axiom EqClassAxiom;
typedef struct subrole_axiom SubRoleAxiom;

typedef struct axiom Axiom;

typedef struct tbox TBox;

// the top concept has the id 0
#define TOP 0

// concept description types
enum concept_description_type {
	ATOMIC_CONCEPT, CONJUNCTION, EXISTENTIAL_RESTRICTION
	// NORMALIZED_CONJUNCTION, NORMALIZED_EXISTENTIAL_RESTRICTION
};

struct atomic_concept {
	int id;
	char* name;
};

// conjunction
struct conjunction {
	int count;
	Concept** conjuncts;
};


// existential restriction
struct existential_restriction {
	Role* role;
	Concept* filler;
};


// concept description
union concept_description {
	// int concept_id;
	AtomicConcept* atomic;
	Conjunction* conj;
	Exists* exists;
}; 
	

// concept description
struct concept {
	enum concept_description_type type;
	ConceptDescription description;
};

///////////////////////////////////////////////////////////////////////////////

// role description types
enum role_description_type {
	ATOMIC_ROLE, ROLE_COMPOSITION // , NORMALIZED_ROLE_COMPOSITION
};

struct atomic_role {
	int id;
	char* name;
};

// role description
// (we represent it with union in case we need role constructors later)
union role_description {
	// int role_id;
	AtomicRole* atomic;
	RoleComposition* role_composition;
}; 
	
// role composition
struct role_composition {
	int size;
	Role** roles;
};

// role 
struct role {
	enum role_description_type type;
	RoleDescription description;
};

///////////////////////////////////////////////////////////////////////////////

union expression {
	Concept* concept;
	Role* role;
};

///////////////////////////////////////////////////////////////////////////////
// axiom types
enum axiom_type {
	SUBCLASS_AX, EQCLASS_AX, SUBROLE_AX
	// NORMALIZED_SUBCLASS_AX, NORMALIZED_SUBROLE_AX
};

// Subclass axiom
struct subclass_axiom {
	Concept* lhs;
	Concept* rhs;
};

// Equivalent class axiom
struct eqclass_axiom {
	Concept* lhs;
	Concept* rhs;
};

// RI
// struct role_inclusion {
struct subrole_axiom {
	Role* lhs;
	Role* rhs;
};


// inclusion axiom
union axiom_body {
	SubClassAxiom* subclass_ax;
	EqClassAxiom* eqclass_ax;
	SubRoleAxiom* subrole_ax;
};

// axiom
struct axiom {
	enum axiom_type type;
	union axiom_body body; 
};

// TBox
struct tbox {
	Axiom** axioms;
	int axiom_count;
};

#endif /*DATATYPES_H_*/
